/*
    http://bhepple.freeshell.org

    Copyright (C) 2010 Bob Hepple <bhepple@freeshell.org>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; see the file COPYING.  If not, write to
    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
    Boston, MA 02111-1307, USA.

*/

/**
 * \file using a dynamic array with callbacks - all elements are the
 * same length.
 *
 * To run from the src directory:
 *
 * libtool --mode=execute valgrind ./tests/array2
 *
 * NB for the purposes of simplicity in illustration, we're ignoring
 * the possibility of OOM conditions here - checking of return values
 * should be done.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <tba.h>

void *xcalloc (size_t nmemb, size_t size) { return(calloc(nmemb, size)); }
void *xmalloc (size_t size) { return(malloc(size)); }
void *xrealloc(void *oldbuf, size_t size) { return(realloc(oldbuf, size)); }
void xfree(void *buf) { free(buf); }

#define DESC_LEN 50

typedef struct {
    int count;
    char *description;
} my_payload;

void print_payload(const my_payload *pl)
{
    printf("%d: desc=%s\n", pl->count, pl->description);
}

static void *free_callback(void *payload, size_t index, void *caller_data)
{
    my_payload *pl = (my_payload *) payload;

    if (pl) {
        if (pl->description) xfree(pl->description);
        xfree(payload);
    }
    return(NULL);
}

static void *create_callback(void *payload, size_t index, void *caller_data)
{
    my_payload *pl = (my_payload *) payload;

    pl->count = index;
    pl->description = xcalloc(1, DESC_LEN);
    snprintf(pl->description, DESC_LEN, "this is payload %zd", index);
    return(pl);
}

static void *copy_callback(void *dest, void *source, size_t index, 
                           void *caller_data)
{
    my_payload *source_payload = (my_payload *) source;
    my_payload *dest_payload = (my_payload *) dest;

    dest_payload->count = source_payload->count;
    dest_payload->description = strdup(source_payload->description);
    return(dest);
}

int main(int argc, char **argv)
{
    // alloc space for 500 my_payloads:
    tba a = tba_new(500, sizeof(my_payload), free_callback, 
                            create_callback, copy_callback, NULL); 
    // a[0..499] are alloc'd; a[500] == NULL
    tba b = NULL;

    print_payload((my_payload *)a[234]);
    print_payload((my_payload *)a[499]);

    // add a new element to the end:
    tba_insert(&a, -1, 1);
    print_payload((my_payload *)a[500]);

    // add 10 new elements at the start:
    tba_insert(&a, 0, 10);
    print_payload((my_payload *)a[5]);
    print_payload((my_payload *)a[10]);

    b = tba_copy(a);
    print_payload((my_payload *)b[467]);

    tba_free(&a);
    tba_free(&b);
    return(0);
}

/* compile this with something like:

cc -Wall -I.. -o array2 array2.c ../.libs/libctoolbox.a

*/
